home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1996 March
/
EnigmA AMIGA RUN 05 (1996)(G.R. Edizioni)(IT)[!][issue 1996-03][Skylink CD IV].iso
/
earcd
/
program
/
ixemlsrc.lha
/
ixemul
/
library
/
ptrace.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-12-23
|
8KB
|
296 lines
/*-
* Copyright (c) 1995 Leonard Norrgard. All rights reserved.
* Copyright (c) 1994 Christopher G. Demetriou. All rights reserved.
* Copyright (c) 1982, 1986, 1989, 1993
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* All or some portions of this file are derived from material licensed
* to the University of California by American Telephone and Telegraph
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
* the permission of UNIX System Laboratories, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from: @(#)sys_process.c 8.1 (Berkeley) 6/10/93
*/
/*
* References:
* (1) Bach's "The Design of the UNIX Operating System",
* (2) sys/miscfs/procfs from UCB's 4.4BSD-Lite distribution,
* (3) the "4.4BSD Programmer's Reference Manual" published
* by USENIX and O'Reilly & Associates.
* The 4.4BSD PRM does a reasonably good job of documenting what the various
* ptrace() requests should actually do, and its text is quoted several times
* in this file.
*/
#define KERNEL
#include "ixemul.h"
#include "kprintf.h"
#include <signal.h>
#include <string.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <exec/execbase.h>
#ifdef DEBUG
#define DP(a) kprintf a
#else
#define DP(a)
#endif
int
process_read_regs (struct user *p, struct reg *regs)
{
bcopy (p->u_regs, regs, sizeof (struct reg));
return 0;
}
int
process_write_regs (struct user *p, struct reg *regs)
{
bcopy (regs, p->u_regs, sizeof (struct reg));
return 0;
}
int
process_sstep (struct user *t, int sstep)
{
if (sstep)
t->u_regs->r_sr |= 0x8000;
else
t->u_regs->r_sr &= ~0x8000;
return 0;
}
int
process_set_pc (struct user *t, caddr_t addr)
{
t->u_regs->r_pc = addr;
return 0;
}
int
ptrace (int request, pid_t pid, caddr_t addr, int data)
{
unsigned long value;
struct Task *task;
struct user *t, *p;
int step;
int error;
/* Find the user area of this process. */
p = FindTask (0)->tc_TrapData;
#ifdef DEBUG
{
char *req;
switch (request)
{
case PT_TRACE_ME: req = "PT_TRACE_ME"; break;
case PT_READ_I: req = "PT_READ_I"; break;
case PT_READ_D: req = "PT_READ_D"; break;
case PT_READ_U: req = "PT_READ_U"; break;
case PT_WRITE_I: req = "PT_WRITE_I"; break;
case PT_WRITE_D: req = "PT_WRITE_D"; break;
case PT_WRITE_U: req = "PT_WRITE_U"; break;
case PT_CONTINUE: req = "PT_CONTINUE"; break;
case PT_KILL: req = "PT_KILL"; break;
case PT_STEP: req = "PT_STEP"; break;
default: req = "*Unknown request*"; break;
}
DP(("ptrace (%s, pid=%lx, addr=%lx, data=%lx);\n",
req, pid, addr, data));
}
#endif
if (request == PT_TRACE_ME)
task = FindTask (0);
else
task = (struct Task *) pid;
t = (struct user *) task->tc_TrapData;
/* Check that the arguments are valid. */
switch (request)
{
case PT_TRACE_ME:
/* Saying that you're being traced is always OK. */
break;
#if 0
/* Can't allow this yet... Must also check that the task is
an ixemul.library one. */
case PT_ATTACH:
/* You can't attach to a process if:
(1) it's the process that's doing the attaching or */
if (t == FindTask (0)->tc_TrapData)
return (EINVAL);
/* (2) it's already being traced. */
if (t->p_flag & STRC)
return (EBUSY);
break;
#endif
case PT_READ_I:
case PT_READ_D:
case PT_READ_U:
case PT_WRITE_I:
case PT_WRITE_D:
case PT_WRITE_U:
case PT_CONTINUE:
case PT_KILL:
#ifdef PT_DETACH
case PT_DETACH:
#endif
#ifdef PT_STEP
case PT_STEP:
#endif
#ifdef PT_GETREGS
case PT_GETREGS:
#endif
#ifdef PT_SETREGS
case PT_SETREGS:
#endif
#ifdef PT_GETFPREGS
case PT_GETFPREGS:
#endif
#ifdef PT_SETFPREGS
case PT_SETFPREGS:
#endif
/* You can't do what you want to the process if: */
/* (1) It's not being traced at all, */
if (!(t->p_flag & STRC))
return EPERM;
/* (2) it's not being traced by _you_, or */
if (t->p_pptr->pr_Task.tc_TrapData != p)
return EBUSY;
/* (3) it's not currently stopped. */
if (t->p_stat != SSTOP
|| !(t->p_flag & SWTED))
return EBUSY;
break;
default:
/* It was not a valid request. */
return EINVAL;
}
/* Now actually do the job. */
step = 0;
switch (request)
{
case PT_TRACE_ME:
/* Child declares it's being traced, just set the trace flag. */
t->p_flag |= STRC;
break;
case PT_READ_I:
case PT_READ_D:
value = (*(unsigned char *) addr) << 8;
value |= *(unsigned char *) (addr + 1);
return value;
case PT_WRITE_I:
case PT_WRITE_D:
*(unsigned char *) addr = data & 0xff;
*(unsigned char *) (addr + 1) = data >> 8 & 0xff;
if (request == PT_WRITE_I)
CacheClearE (addr, 2, CACRF_ClearI);
else
CacheClearE (addr, 2, CACRF_ClearD);
return 0;
/* case PT_READ_U: fixme */
/* case PT_WRITE_U: fixme */
case PT_STEP:
/* From the 4.4BSD PRM:
"Execution continues as in request PT_CONTINUE; however
as soon as possible after execution of at least one
instruction, execution stops again. [ ... ]" */
step = 1;
/* fallthrough */
case PT_CONTINUE:
/* From the 4.4BSD PRM:
"The data argument is taken as a signal number and the
child's execution continues at location addr as if it
incurred that signal. Normally the signal number will
be either 0 to indicate that the signal that caused the
stop should be ignored, or that value fetched out of
the process's image indicating which signal caused
the stop. If addr is (int *)1 then execution continues
from where it stopped." */
/* step = 0 done above. */
/* Check that data is a valid signal number or zero. */
if (data < 0 || data >= NSIG)
return EINVAL;
/* Arrange for a single-step, if that's requested and possible. */
if ((error = process_sstep (t, step)))
return error;
/* If the address parameter is not (int *)1, set the pc. */
if ((int *)addr != (int *)1)
if ((error = process_set_pc (t, addr)))
return error;
/* Finally, deliver the requested signal (or none). */
sendsig:
t->p_xstat = data;
setrun (task);
return 0;
case PT_KILL:
/* Just send the process a KILL signal. */
data = SIGKILL;
goto sendsig;
/* More to come... fixme. */
default:
/* Unknown request. */
errno = EIO;
return -1;
}
return 0; /* correct return value? */
}